home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / Imaging / TrnsfrmB.cpp < prev   
Encoding:
Text File  |  1997-02-13  |  27.8 KB  |  967 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        TrnsfrmB.cp
  3.  
  4.     Contains:    Implementation of ODBaseTransform
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1993 - 1995 Apple Computer, Inc. All rights reserved.
  9.  
  10.     Change History (most recent first):
  11.     
  12.          <5>      11/14/96    TJ        #1401258 Fixed the definition of VOID.
  13.          <2>     1/15/96    TJ        Cleaned Up
  14.         <18>     10/8/95    TJ        Fixes Recomended by Refball
  15.         <17>     9/13/95    DM        1277216 GM:API return no ODPoints nor
  16.                                     ODPolygons
  17.         <16>      9/8/95    jpa        Use SET_SOM_EXCEPTION [1281031]
  18.         <15>     8/18/95    NP        1274946:
  19.                                     kODErrInvalidParameter->kODErrIllegalNullIn
  20.                                     put
  21.         <14>     8/16/95    jpa        Use ODGet/SetMatrixProp in ReadFrom/WriteTo
  22.                                     [1276814]
  23.         <13>     8/12/95    TÇ        1276808 Call ODReleaseObject instead of
  24.                                     ODDeleteObject on shapes & transforms
  25.         <12>      8/3/95    RR        #1257260: Collapse B classes. Remove
  26.                                     somInit methods. Don't call IsInitialized
  27.                                     or SubclassResponsibility
  28.         <11>     3/20/95    jpa        SOM_CATCH --> SOM_TRY [1224355]
  29.         <10>    12/20/94    VL        1195012: Make Storage calls be
  30.                                     marshallable.
  31.          <9>    12/20/94    jpa        Added composite xform support [1205794]
  32.          <8>     12/5/94    jpa        Code-review fixes, error handling & such.
  33.                                     [1203923]
  34.          <7>     9/29/94    RA        1189812: Mods for 68K build.
  35.          <6>      9/9/94    jpa        Added Release method, and verify refcnt in
  36.                                     somUninit. [1185660]
  37.          <5>     8/17/94    jpa        Function prefixes. [1181512]
  38.          <4>      8/8/94    jpa        Added NewTransform [1179574]
  39.          <3>     7/15/94    jpa        CopyFrom now calls InitBaseTransform in
  40.                                     case caller had just created the object.
  41.          <2>     6/30/94    jpa        Ported implementation to SOM.
  42.          <1>     6/15/94    jpa        first checked in (stubs)
  43.          ---------------------------Moved to ODSOM project.
  44.          <6>     5/27/94    jpa        Fixed bug in ScaleBy, noticed while copying
  45.                                     code over to SOM.
  46.          <5>      5/9/94    jpa        Use new built-in matrix code. [1162092]
  47.          <4>     3/25/94    JA        Rewrote & changed API to support scaling
  48.                                     for QD parts. (1153438)
  49.          <3>     3/15/94    MB        Changes to support SCpp/ASLM builds,
  50.                                     #1150864.
  51.          <2>     2/16/94    JA        Include new AltPoint.h.
  52.         <15>      2/7/94    JA        Further tigerings.
  53.         <14>      2/3/94    JA        Tiger Team Makeover!
  54.         <13>     12/3/93    TÇ        Stop including ODError.h, it is included
  55.                                     as ErrorDef.h inside Except.h
  56.         <12>    11/23/93    JA        Minor tweaks.
  57.         <11>    10/14/93    JA        No more copying in get/setters.
  58.          <9>     10/6/93    JA        Use new fixed-point ODPoint.
  59.          <8>     9/23/93    JA        Restored MoveBy. Added Mac-specific
  60.                                     convenience methods.
  61.          <7>     9/22/93    JA        Oops! Removed leftover line of test code.
  62.          <6>     9/22/93    JA        Updated ASSERTs for new macro.
  63.          <5>     9/20/93    JA        Post-brownies: Okay, REALLY fixed
  64.                                     ReadPlatformTransform.
  65.          <4>     9/17/93    TÇ        fixed ReadPlatformTransform
  66.          <3>     9/16/93    JA        Added Read/WritePlatformTransform. Removed
  67.                                     constructor w/params. Use copy-in, copy-out
  68.                                     semantics.
  69.          <2>     9/07/93    jpa        Fleshed out class, cleverly letting GX do the matrix grunge.
  70.          <1>     8/18/93    TÇ        first checked in
  71.          <0>     8/18/93    JBS        created
  72.     
  73.     Theory Of Operation:
  74.     
  75.         An ODBaseTransform is mostly a holder for an ODMatrix. It also caches an
  76.         inverse of its matrix for use in InvertPoint and Invert operations.
  77.         Since it is possible for subclasses of ODBaseTransform to exist that do not
  78.         use matrices (nonlinear transforms like morphs or spherizers), it must be
  79.         able to coexist with these. They can be detected by sending them a
  80.         HasMatrix message. The major problem arises when I'm asked to compose
  81.         myself with one of these; matrix multiplication is right out, so I have
  82.         to keep around a copy of the other transform and do manual composition. In
  83.         fact I have to keep around two potential transforms, one for pre-composi-
  84.         tion and one for post-composition.
  85.         It is illegal to externalize a composite transform, since this would be
  86.         difficult to implement. In practice the only transforms that get extern-
  87.         alized are frames' internal transforms, which are probably not composite.
  88.         
  89.         Anyone wanting to implement nonlinear transforms needs to subclass
  90.         ODBaseTransform and override at least the following methods:
  91.             GetMatrix    [need to throw ODErrTransformErr]
  92.             HasMatrix    [need to return false]
  93.             Reset
  94.             Copy
  95.             CopyFrom
  96.             Invert
  97.             PreCompose
  98.             PostCompose
  99.             TransformPoint
  100.             InvertPoint
  101.             TransformShape
  102.             InvertShape
  103.             WriteTo
  104.             ReadFrom
  105.  
  106.     To Do:
  107.     In Progress:
  108.         
  109. */
  110.  
  111. #ifndef _PLFMDEF_
  112. #include "PlfmDef.h"
  113. #endif
  114.  
  115. #ifndef _ALTPOINT_
  116. #include "AltPoint.h"            /* Use C++ savvy ODPoint and ODRect*/
  117. #endif
  118.  
  119.  
  120. #define ODBaseTransform_Class_Source
  121. #define VARIABLE_MACROS
  122. #include <TrnsfrmB.xih>
  123.  
  124.  
  125. #ifndef SOM_ODTransform_xh
  126. #include "Trnsform.xh"
  127. #endif
  128.  
  129. #ifndef _MATRIX_
  130. #include "Matrix.h"
  131. #endif
  132.  
  133. #ifndef _ODMATH_
  134. #include "ODMath.h"
  135. #endif
  136.  
  137. #ifndef SOM_ODShape_xh
  138. #include <Shape.xh>
  139. #endif
  140.  
  141. #ifndef _ODUTILS_
  142. #include <ODUtils.h>
  143. #endif
  144.  
  145. #ifndef _EXCEPT_
  146. #include "Except.h"
  147. #endif
  148.  
  149. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  150. #include <StdTypes.xh>
  151. #endif
  152.  
  153. #ifndef SOM_ODStorageUnit_xh
  154. #include <StorageU.xh>
  155. #endif
  156.  
  157. #ifndef _ODDEBUG_
  158. #include "ODDebug.h"
  159. #endif
  160.  
  161. #ifndef _LINEOPS_
  162. #include "LineOps.h"                    /* For kFixedEpsilon */
  163. #endif
  164.  
  165. #ifndef _STDTYPIO_
  166. #include <StdTypIO.h>
  167. #endif
  168.  
  169. #ifndef _STORUTIL_
  170. #include <StorUtil.h>
  171. #endif
  172.  
  173.  
  174. #define BAIL_IF_NULL(PARAM,VAL) \
  175.             if( (PARAM)!=kODNULL ) ; else {                        \
  176.                 WARN("Invalid NULL parameter " #PARAM);            \
  177.                 ODSetSOMException(ev, kODErrIllegalNullInput);    \
  178.                 return VAL;                                        \
  179.             }
  180.             
  181. #ifdef VOID
  182. #undef VOID
  183. #endif
  184.  
  185. #define VOID /**/
  186.  
  187.  
  188. #pragma segment ODTransform
  189.  
  190.  
  191. //==============================================================================
  192. // HOUSEKEEPING
  193. //==============================================================================
  194.  
  195.  
  196. //------------------------------------------------------------------------------
  197. //    somUninit
  198. //------------------------------------------------------------------------------
  199.  
  200. SOM_Scope void  SOMLINK ODBaseTransform__somUninit(ODBaseTransform *somSelf)
  201. {
  202.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  203.     ODBaseTransformMethodDebug("ODBaseTransform","somUninit");
  204.    
  205.     ODDeleteObject(_fInverseMatrix);
  206.     ODSafeReleaseObject(_fPreTransform);
  207.     ODSafeReleaseObject(_fPostTransform);
  208.     
  209.     ODBaseTransform_parents_somUninit(somSelf);
  210.  
  211. }
  212.  
  213. //------------------------------------------------------------------------------
  214. //    InitBaseTransform
  215. //------------------------------------------------------------------------------
  216.  
  217. SOM_Scope void  SOMLINK ODBaseTransform__InitBaseTransform(ODBaseTransform *somSelf, Environment *ev)
  218. {
  219.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  220.     ODBaseTransformMethodDebug("ODBaseTransform","ODBaseTransformInitBaseTransform");
  221.  
  222.     SOM_TRY
  223.     
  224.     /* Moved from somInit. SOM itself sets fields to zero
  225.     _fInverseMatrix = kODNULL;
  226.     _fPreTransform = kODNULL;
  227.     _fPostTransform = kODNULL;
  228.     */
  229.     _fType = kODIdentityXform;
  230.     _fMatrix = kODIdentityMatrix;
  231.     
  232.     somSelf->InitRefCntObject(ev);
  233.     
  234.     SOM_CATCH_ALL
  235.     SOM_ENDTRY
  236. }
  237.  
  238. //------------------------------------------------------------------------------
  239. //    Release
  240. //------------------------------------------------------------------------------
  241.  
  242. SOM_Scope void  SOMLINK ODBaseTransform__Release(ODBaseTransform *somSelf, Environment *ev)
  243. {
  244. //    ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  245.     ODBaseTransformMethodDebug("ODBaseShape","Release");
  246.  
  247.     SOM_TRY
  248.  
  249.     ODBaseTransform_parents_Release(somSelf,ev);
  250.     
  251.     // Delete myself when my refCount goes to zero:
  252.     if( somSelf->GetRefCount(ev) < 1 )
  253.         delete somSelf;
  254.  
  255.     SOM_CATCH_ALL
  256.     SOM_ENDTRY
  257. }
  258.  
  259. //------------------------------------------------------------------------------
  260. //    Purge
  261. //------------------------------------------------------------------------------
  262.  
  263. SOM_Scope ODSize  SOMLINK ODBaseTransform__Purge(ODBaseTransform *somSelf, Environment *ev,
  264.         ODSize size)
  265. {
  266.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  267.     ODBaseTransformMethodDebug("ODBaseTransform","Purge");
  268.  
  269.     ODSize purged = 0;
  270.     ODVolatile(purged);
  271.     
  272.     SOM_TRY
  273.     
  274.         if( _fInverseMatrix ) {
  275.             ODDeleteObject(_fInverseMatrix);
  276.             purged = sizeof(ODMatrix);
  277.         }
  278.         else
  279.             purged = 0;
  280.  
  281.         purged += parent_Purge(somSelf,ev,size);
  282.     
  283.     SOM_CATCH_ALL
  284.         WARN("Error %ld trying to purge in ODBaseTransform__Purge",ErrorCode());
  285.         SetErrorCode(kODNoError);        // dh - Eat the exception; Purge should not 
  286.                                         // propagate it because clients function
  287.                                         // fine whether memory was purged or not.
  288.     SOM_ENDTRY
  289.  
  290.     return purged;
  291. }
  292.  
  293.  
  294. //==============================================================================
  295. // GETTERS
  296. //==============================================================================
  297.  
  298.  
  299. //------------------------------------------------------------------------------
  300. //    GetType
  301. //------------------------------------------------------------------------------
  302.  
  303. SOM_Scope ODTransformType SOMLINK ODBaseTransform__GetType(ODBaseTransform *somSelf, Environment *ev)
  304. {
  305.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  306.     ODBaseTransformMethodDebug("ODBaseTransform","GetType");
  307.  
  308.     if( _fPreTransform || _fPostTransform )
  309.         return kODUnknownXform;
  310.     else
  311.         return _fType;
  312. }
  313.  
  314. //------------------------------------------------------------------------------
  315. //    GetMatrix
  316. //------------------------------------------------------------------------------
  317.  
  318. SOM_Scope void SOMLINK ODBaseTransform__GetMatrix(ODBaseTransform *somSelf, Environment *ev,
  319.          ODMatrix *m )
  320. {
  321.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  322.     ODBaseTransformMethodDebug("ODBaseTransform","GetMatrix");
  323.  
  324.     BAIL_IF_NULL(m,VOID);
  325.     *m = _fMatrix;
  326.     if( _fPreTransform || _fPostTransform )
  327.         ODSetSOMException(ev,kODErrTransformErr);
  328. }
  329.  
  330. //------------------------------------------------------------------------------
  331. //    HasMatrix
  332. //------------------------------------------------------------------------------
  333.  
  334. SOM_Scope ODBoolean SOMLINK ODBaseTransform__HasMatrix(ODBaseTransform *somSelf, Environment *ev)
  335. {
  336.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  337.     ODBaseTransformMethodDebug("ODBaseTransform","HasMatrix");
  338.  
  339.     return _fPreTransform==kODNULL && _fPostTransform==kODNULL;
  340. }
  341.  
  342. //------------------------------------------------------------------------------
  343. //    GetOffset
  344. //------------------------------------------------------------------------------
  345.  
  346. SOM_Scope void SOMLINK ODBaseTransform__GetOffset(ODBaseTransform *somSelf, Environment *ev,
  347.          ODPoint *p )
  348. {
  349.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  350.     ODBaseTransformMethodDebug("ODBaseTransform","GetOffset");
  351.  
  352.     BAIL_IF_NULL(p,VOID);
  353.     p->x = ODFractDivide(_fMatrix.m[2][0], _fMatrix.m[2][2]);
  354.     p->y = ODFractDivide(_fMatrix.m[2][1], _fMatrix.m[2][2]);
  355. }
  356.  
  357. //------------------------------------------------------------------------------
  358. //    GetScale
  359. //------------------------------------------------------------------------------
  360.  
  361. SOM_Scope void SOMLINK ODBaseTransform__GetScale(ODBaseTransform *somSelf, Environment *ev,
  362.          ODPoint *scale )
  363. {
  364.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  365.     ODBaseTransformMethodDebug("ODBaseTransform","GetScale");
  366.  
  367.     BAIL_IF_NULL(scale,VOID);
  368.     scale->x = ODFractDivide(_fMatrix.m[0][0], _fMatrix.m[2][2]);
  369.     scale->y = ODFractDivide(_fMatrix.m[1][1], _fMatrix.m[2][2]);
  370. }
  371.  
  372. //------------------------------------------------------------------------------
  373. //    GetPreScaleOffset
  374. //------------------------------------------------------------------------------
  375.  
  376. SOM_Scope void SOMLINK ODBaseTransform__GetPreScaleOffset(ODBaseTransform *somSelf, Environment *ev,
  377.          ODPoint *offset )
  378. {
  379.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  380.     ODBaseTransformMethodDebug("ODBaseTransform","GetPreScaleOffset");
  381.  
  382.     // This returns the offset to use if you are going to apply the offset
  383.     // _before_ scaling. Just divide the translation elements by the scales.
  384.     
  385.     BAIL_IF_NULL(offset,VOID);
  386.     offset->x = ODFixedDivide(_fMatrix.m[2][0],_fMatrix.m[0][0]);
  387.     offset->y = ODFixedDivide(_fMatrix.m[2][1],_fMatrix.m[1][1]);
  388.     
  389.     if( offset->x==kODFixedInfinity || offset->x==kODFixedMinusInfinity
  390.       ||offset->y==kODFixedInfinity || offset->y==kODFixedMinusInfinity )
  391.             ODSetSOMException(ev,kODErrTransformErr);
  392. }
  393.  
  394. //------------------------------------------------------------------------------
  395. //    IsSameAs
  396. //------------------------------------------------------------------------------
  397.  
  398. static ODBoolean Neq( ODFixed a, ODFixed b )
  399. {
  400.     return (a-b > kFixedEpsilon) || (a-b < -kFixedEpsilon);
  401. }
  402.  
  403. SOM_Scope ODBoolean SOMLINK ODBaseTransform__IsSameAs(ODBaseTransform *somSelf, Environment *ev,
  404.          ODTransform *xform )
  405. {
  406.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  407.     ODBaseTransformMethodDebug("ODBaseTransform","IsSameAs");
  408.  
  409.     SOM_TRY
  410.     
  411.     BAIL_IF_NULL(xform,kODFalse);
  412.     
  413.     if( _fPreTransform || _fPostTransform )
  414.         return kODFalse;                    // ????? What else can I do??
  415.  
  416.     if( (ODBaseTransform*)xform != somSelf) {
  417.         ODMatrix m0, m1, *mp;
  418.         xform->GetMatrix(ev,&m1);
  419.         
  420.         if(_fMatrix.m[2][2]!=kODFract1 ) {
  421.             m0 = _fMatrix;
  422.             MxNormalize(&m0);                // Normalize my matrix
  423.             mp = &m0;
  424.         } else
  425.             mp = &_fMatrix;
  426.         if(m1.m[2][2]!=kODFract1 )
  427.             MxNormalize(&m1);                // Normalize other matrix
  428.             
  429.         for( long i=8; i>=0; i-- )
  430.             if( Neq(mp->m[0][i],m1.m[0][i]) )    // Compare matrices
  431.                 return kODFalse;
  432.     }
  433.     return kODTrue;
  434.  
  435.     SOM_CATCH_ALL
  436.     SOM_ENDTRY
  437.     return kODFalse;
  438. }
  439.  
  440.  
  441. //==============================================================================
  442. // SETTERS
  443. //==============================================================================
  444.  
  445.  
  446. //------------------------------------------------------------------------------
  447. //    SetMatrix
  448. //------------------------------------------------------------------------------
  449.  
  450. SOM_Scope ODTransform* SOMLINK ODBaseTransform__SetMatrix(ODBaseTransform *somSelf, Environment *ev,
  451.          ODMatrix *m )
  452. {
  453.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  454.     ODBaseTransformMethodDebug("ODBaseTransform","SetMatrix");
  455.  
  456.     SOM_TRY
  457.     
  458.     if( m == kODNULL )
  459.         somSelf->Reset(ev);
  460.     else {
  461.         ODTransformType type = MxType(m);
  462.         if( type==kODUnknownXform )
  463.             THROW(kODErrTransformErr);
  464.         _fMatrix = *m;
  465.         _fType = type;
  466.         ODDeleteObject(_fInverseMatrix);
  467.         ODReleaseObject(ev,_fPreTransform);
  468.         ODReleaseObject(ev,_fPostTransform);
  469.     }
  470.  
  471.     SOM_CATCH_ALL
  472.     SOM_ENDTRY
  473.     return (ODTransform*) somSelf;
  474. }
  475.  
  476. //------------------------------------------------------------------------------
  477. //    Reset
  478. //------------------------------------------------------------------------------
  479.  
  480. SOM_Scope ODTransform* SOMLINK ODBaseTransform__Reset(ODBaseTransform *somSelf, Environment *ev)
  481. {
  482.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  483.     ODBaseTransformMethodDebug("ODBaseTransform","Reset");
  484.  
  485.     _fMatrix = kODIdentityMatrix;
  486.     _fType = kODIdentityXform;
  487.     ODDeleteObject(_fInverseMatrix);
  488.     ODSafeReleaseObject(_fPreTransform);    _fPreTransform = kODNULL;
  489.     ODSafeReleaseObject(_fPostTransform);_fPostTransform= kODNULL;
  490.     return (ODTransform*) somSelf;
  491. }
  492.  
  493. //------------------------------------------------------------------------------
  494. //    NewTransform
  495. //------------------------------------------------------------------------------
  496.  
  497. SOM_Scope ODTransform*  SOMLINK ODBaseTransform__NewTransform(ODBaseTransform *somSelf, Environment *ev)
  498. {
  499. //    ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  500.     ODBaseTransformMethodDebug("ODBaseTransform","NewTransform");
  501.     
  502.     ODTransform *x = new ODTransform;
  503.     if( !x )
  504.         ODSetSOMException(ev,kODErrOutOfMemory);
  505.     else {
  506.         TRY{
  507.             x->InitTransform(ev);
  508.         }CATCH_ALL{
  509.             ODSafeReleaseObject(x);
  510.             SET_SOM_EXCEPTION(ev);
  511.         }ENDTRY
  512.     }
  513.     return x;
  514. }
  515.  
  516. //------------------------------------------------------------------------------
  517. //    Copy
  518. //------------------------------------------------------------------------------
  519.  
  520. SOM_Scope ODTransform* SOMLINK ODBaseTransform__Copy(ODBaseTransform *somSelf, Environment *ev )
  521. {
  522.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  523.     ODBaseTransformMethodDebug("ODBaseTransform","Copy");
  524.  
  525.     ODTransform *x = kODNULL; ODVolatile(x);
  526.     
  527.     SOM_TRY
  528.     
  529.         x = new ODTransform;
  530.         THROW_IF_NULL(x);
  531.         x->InitTransform(ev);
  532.         x->SetMatrix(ev,&_fMatrix);
  533.         if( _fPreTransform ) {
  534.             ODTransform *t = _fPreTransform->Copy(ev);
  535.             x->PreCompose(ev,t);
  536.             t->Release(ev);
  537.         }
  538.         if( _fPostTransform ) {
  539.             ODTransform *t = _fPostTransform->Copy(ev);
  540.             x->PostCompose(ev,t);
  541.             t->Release(ev);
  542.         }
  543.     
  544.     SOM_CATCH_ALL
  545.         ODSafeReleaseObject(x);
  546.         x = kODNULL;
  547.     SOM_ENDTRY
  548.     return x;
  549. }
  550.  
  551. //------------------------------------------------------------------------------
  552. //    CopyFrom
  553. //------------------------------------------------------------------------------
  554.  
  555. SOM_Scope ODTransform* SOMLINK ODBaseTransform__CopyFrom(ODBaseTransform *somSelf, Environment *ev,
  556.          ODTransform *xform )
  557. {
  558.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  559.     ODBaseTransformMethodDebug("ODBaseTransform","CopyFrom");
  560.  
  561.     SOM_TRY
  562.     
  563.     BAIL_IF_NULL(xform,kODNULL);
  564.  
  565.     if( xform->HasMatrix(ev) ) {
  566.         xform->GetMatrix(ev,&_fMatrix);
  567.         _fType = xform->GetType(ev);
  568.         ODDeleteObject(_fInverseMatrix);
  569.     } else {
  570.         somSelf->Reset(ev);
  571.         _fPreTransform = xform->Copy(ev);
  572.     }
  573.  
  574.     SOM_CATCH_ALL
  575.     SOM_ENDTRY
  576.     return (ODTransform*) somSelf;
  577. }
  578.  
  579.  
  580. //==============================================================================
  581. // MATRIX TRANSFORMATIONS
  582. //==============================================================================
  583.  
  584.  
  585. //------------------------------------------------------------------------------
  586. //    SetOffset
  587. //------------------------------------------------------------------------------
  588.  
  589. SOM_Scope ODTransform* SOMLINK ODBaseTransform__SetOffset(ODBaseTransform *somSelf, Environment *ev,
  590.          ODPoint *offset )
  591. {
  592.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  593.     ODBaseTransformMethodDebug("ODBaseTransform","SetOffset");
  594.  
  595.     SOM_TRY
  596.     
  597.     somSelf->Reset(ev);
  598.     _fMatrix.m[2][0] = offset->x;
  599.     _fMatrix.m[2][1] = offset->y;
  600.     _fType = kODTranslateXform;
  601.  
  602.     SOM_CATCH_ALL
  603.     SOM_ENDTRY
  604.     return (ODTransform*) somSelf;
  605. }
  606.  
  607. //------------------------------------------------------------------------------
  608. //    MoveBy
  609. //------------------------------------------------------------------------------
  610.  
  611. SOM_Scope ODTransform* SOMLINK ODBaseTransform__MoveBy(ODBaseTransform *somSelf, Environment *ev,
  612.          ODPoint *offset )
  613. {
  614.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  615.     ODBaseTransformMethodDebug("ODBaseTransform","MoveBy");
  616.  
  617.     SOM_TRY
  618.     
  619.     ODMatrix m = _fMatrix;
  620.     if( MxMove(&m,_fType,offset->x,offset->y) )
  621.         THROW(kODErrTransformErr);
  622.     somSelf->SetMatrix(ev, &m);
  623.  
  624.     SOM_CATCH_ALL
  625.     SOM_ENDTRY
  626.     return (ODTransform*) somSelf;
  627. }
  628.  
  629. //------------------------------------------------------------------------------
  630. //    ScaleBy
  631. //------------------------------------------------------------------------------
  632.  
  633. SOM_Scope ODTransform* SOMLINK ODBaseTransform__ScaleBy(ODBaseTransform *somSelf, Environment *ev,
  634.          ODPoint *scale )
  635. {
  636.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  637.     ODBaseTransformMethodDebug("ODBaseTransform","ScaleBy");
  638.  
  639.     SOM_TRY
  640.     
  641.     ODMatrix m = _fMatrix;
  642.     if( MxScale(&m,scale->x,scale->y) )
  643.         THROW(kODErrTransformErr);
  644.     somSelf->SetMatrix(ev, &m);
  645.  
  646.     SOM_CATCH_ALL
  647.     SOM_ENDTRY
  648.     return (ODTransform*) somSelf;
  649. }
  650.  
  651. //------------------------------------------------------------------------------
  652. //    ScaleDownBy
  653. //------------------------------------------------------------------------------
  654.  
  655. SOM_Scope ODTransform* SOMLINK ODBaseTransform__ScaleDownBy(ODBaseTransform *somSelf, Environment *ev,
  656.          ODPoint *scale )
  657. {
  658.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  659.     ODBaseTransformMethodDebug("ODBaseTransform","ScaleDownBy");
  660.  
  661.     SOM_TRY
  662.     
  663.     if( scale->x==0 || scale->y==0 )
  664.         THROW(kODErrTransformErr);
  665.     ODPoint s;
  666.     s.x = ODFixedDivide(kODFixed1,scale->x);
  667.     s.y = ODFixedDivide(kODFixed1,scale->y);
  668.     somSelf->ScaleBy(ev, &s);
  669.  
  670.     SOM_CATCH_ALL
  671.     SOM_ENDTRY
  672.     return (ODTransform*) somSelf;
  673. }
  674.  
  675. //------------------------------------------------------------------------------
  676. //    BuildInverse
  677. //------------------------------------------------------------------------------
  678.  
  679. SOM_Scope void SOMLINK ODBaseTransform__BuildInverse(ODBaseTransform *somSelf, Environment *ev)
  680. {
  681.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  682.     ODBaseTransformMethodDebug("ODBaseTransform","BuildInverse");
  683.  
  684.     SOM_TRY
  685.     
  686.     WASSERT(!_fInverseMatrix);
  687.     _fInverseMatrix = new ODMatrix;
  688.     if( MxInverse(&_fMatrix,_fType, _fInverseMatrix) ) {
  689.         ODDeleteObject(_fInverseMatrix);
  690.         THROW(kODErrTransformErr);
  691.     }
  692.     
  693.     SOM_CATCH_ALL
  694.     SOM_ENDTRY
  695. }
  696.  
  697. //------------------------------------------------------------------------------
  698. //    Invert
  699. //------------------------------------------------------------------------------
  700.  
  701. SOM_Scope ODTransform* SOMLINK ODBaseTransform__Invert(ODBaseTransform *somSelf, Environment *ev )
  702. {
  703.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  704.     ODBaseTransformMethodDebug("ODBaseTransform","Invert");
  705.     
  706.     SOM_TRY
  707.  
  708.     if( !_fInverseMatrix )
  709.         somSelf->BuildInverse(ev);
  710.     
  711.     if( _fPreTransform || _fPostTransform ) {
  712.         // When inverting, switch pre with post and invert each one.
  713.         ODBaseTransform *pre = _fPreTransform;
  714.         _fPreTransform = _fPostTransform ?_fPostTransform->Invert(ev) :kODNULL;
  715.         _fPostTransform = pre ?pre->Invert(ev) :kODNULL;
  716.     }
  717.     
  718.     // Swap matrix with inverse:
  719.     ODFixed *a = &_fMatrix.m[0][0];
  720.     ODFixed *b = &_fInverseMatrix->m[0][0];
  721.     for( ODSLong i=9; i>0; i-- ) {
  722.         register ODFixed temp = *a;
  723.         *(a++) = *b;
  724.         *(b++) = temp;
  725.     }
  726.     
  727.     // No need to change _fType, since matrix and inverse have same type.
  728.     
  729.     SOM_CATCH_ALL
  730.     SOM_ENDTRY
  731.     return (ODTransform*) somSelf;
  732. }
  733.  
  734. //------------------------------------------------------------------------------
  735. //    PreCompose
  736. //------------------------------------------------------------------------------
  737.  
  738. SOM_Scope ODTransform* SOMLINK ODBaseTransform__PreCompose(ODBaseTransform *somSelf, Environment *ev,
  739.          ODTransform *t )
  740. {
  741.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  742.     ODBaseTransformMethodDebug("ODBaseTransform","PreCompose");
  743.  
  744.     SOM_TRY
  745.     BAIL_IF_NULL(t,kODNULL);
  746.     
  747.     if( _fPreTransform )
  748.         _fPreTransform->PreCompose(ev,t);
  749.     else if( !t->HasMatrix(ev) )
  750.         _fPreTransform = t->Copy(ev);
  751.     else {
  752.         ODMatrix m;
  753.         t->GetMatrix(ev,&m);
  754.         if( MxConcat( &_fMatrix,_fType, &m,t->GetType(ev) ) )    // m = m * _fMatrix
  755.             THROW(kODErrTransformErr);
  756.         somSelf->SetMatrix(ev, &m);
  757.     }
  758.  
  759.     SOM_CATCH_ALL
  760.     SOM_ENDTRY
  761.     return (ODTransform*) somSelf;
  762. }
  763.  
  764. //------------------------------------------------------------------------------
  765. //    PostCompose
  766. //------------------------------------------------------------------------------
  767.  
  768. SOM_Scope ODTransform* SOMLINK ODBaseTransform__PostCompose(ODBaseTransform *somSelf, Environment *ev,
  769.          ODTransform *t )
  770. {
  771.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  772.     ODBaseTransformMethodDebug("ODBaseTransform","PostCompose");
  773.  
  774.     SOM_TRY
  775.     BAIL_IF_NULL(t,kODNULL);
  776.     
  777.     if( _fPostTransform )
  778.         _fPostTransform->PostCompose(ev,t);
  779.     else if( !t->HasMatrix(ev) )
  780.         _fPostTransform = t->Copy(ev);
  781.     else {
  782.         ODMatrix m;
  783.         ODMatrix me = _fMatrix;
  784.         t->GetMatrix(ev,&m);
  785.         if( MxConcat( &m,t->GetType(ev), &me,_fType) )                // me = me * m
  786.             THROW(kODErrTransformErr);
  787.         somSelf->SetMatrix(ev, &me);
  788.     }
  789.  
  790.     SOM_CATCH_ALL
  791.     SOM_ENDTRY
  792.     return (ODTransform*) somSelf;
  793. }
  794.  
  795. //------------------------------------------------------------------------------
  796. //    TransformPoint
  797. //------------------------------------------------------------------------------
  798.  
  799. SOM_Scope void SOMLINK ODBaseTransform__TransformPoint(ODBaseTransform *somSelf, Environment *ev,
  800.          ODPoint *pt )
  801. {
  802.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  803.     ODBaseTransformMethodDebug("ODBaseTransform","TransformPoint");
  804.     
  805.     ODPoint xp = *pt;
  806.     
  807.     SOM_TRY
  808.  
  809.     if( _fPreTransform )
  810.         _fPreTransform->TransformPoint(ev,&xp);
  811.     if( MxMul(&_fMatrix,_fType, &xp,1) )
  812.         THROW(kODErrTransformErr);
  813.     if( _fPostTransform )
  814.         _fPostTransform->TransformPoint(ev,&xp);
  815.  
  816.     *pt = xp;
  817.     
  818.     SOM_CATCH_ALL
  819.     SOM_ENDTRY
  820. }
  821.  
  822. //------------------------------------------------------------------------------
  823. //    InvertPoint
  824. //------------------------------------------------------------------------------
  825.  
  826. SOM_Scope void SOMLINK ODBaseTransform__InvertPoint(ODBaseTransform *somSelf, Environment *ev,
  827.          ODPoint *pt )
  828. {
  829.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  830.     ODBaseTransformMethodDebug("ODBaseTransform","InvertPoint");
  831.  
  832.     ODPoint inv = *pt;
  833.  
  834.     SOM_TRY
  835.  
  836.     if( !_fInverseMatrix )
  837.         somSelf->BuildInverse(ev);
  838.     
  839.     if( _fPostTransform )
  840.         _fPostTransform->InvertPoint(ev,&inv);
  841.     if( MxMul(_fInverseMatrix,_fType, &inv,1) )
  842.         THROW(kODErrTransformErr);
  843.     if( _fPreTransform )
  844.         _fPreTransform->InvertPoint(ev,&inv);
  845.         
  846.     *pt = inv;
  847.  
  848.     SOM_CATCH_ALL
  849.     SOM_ENDTRY
  850. }
  851.  
  852. //------------------------------------------------------------------------------
  853. //    TransformShape
  854. //------------------------------------------------------------------------------
  855.  
  856. SOM_Scope void SOMLINK ODBaseTransform__TransformShape(ODBaseTransform *somSelf, Environment *ev,
  857.          ODShape *shape )
  858. {
  859.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  860.     ODBaseTransformMethodDebug("ODBaseTransform","TransformShape");
  861.  
  862.     SOM_TRY
  863.     
  864.     BAIL_IF_NULL(shape,VOID);
  865.     if( _fPreTransform )
  866.         _fPreTransform->TransformShape(ev,shape);
  867.     shape->Transform(ev, (ODTransform*)somSelf);
  868.     if( _fPostTransform )
  869.         _fPostTransform->TransformShape(ev,shape);
  870.     
  871.     /*    This call is (a) a convenience for clients and (b) provided for
  872.         implementations of non-affine transformations, i.e. transformations
  873.         that do not map straight lines onto straight lines. ODShapes trans-
  874.         form themselves by running all their control points through the
  875.         transform. For a non-affine transformation this is not sufficient
  876.         and the transform itself will have to do the work. In fact, if
  877.         the transform has no matrix (HasMatrix()==false), then the body of
  878.         this method must _not_ call ODShape::Transform(somSelf) or an endless
  879.         recursion will result! (Look at ODShape::Transform to see why.)
  880.     */
  881.  
  882.     SOM_CATCH_ALL
  883.     SOM_ENDTRY
  884. }
  885.  
  886. //------------------------------------------------------------------------------
  887. //    InvertShape
  888. //------------------------------------------------------------------------------
  889.  
  890. SOM_Scope void SOMLINK ODBaseTransform__InvertShape(ODBaseTransform *somSelf, Environment *ev,
  891.          ODShape *shape )
  892. {
  893.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  894.     ODBaseTransformMethodDebug("ODBaseTransform","InvertShape");
  895.  
  896.     SOM_TRY
  897.     
  898.     BAIL_IF_NULL(shape,VOID);
  899.     if( _fPostTransform )
  900.         _fPostTransform->TransformShape(ev,shape);
  901.     shape->InverseTransform(ev, (ODTransform*)somSelf);
  902.     if( _fPreTransform )
  903.         _fPreTransform->TransformShape(ev,shape);
  904.     
  905.     // See above comment in TransformShape.
  906.  
  907.     SOM_CATCH_ALL
  908.     SOM_ENDTRY
  909. }
  910.  
  911.  
  912. //==============================================================================
  913. // INPUT / OUTPUT
  914. //==============================================================================
  915.  
  916.  
  917. //------------------------------------------------------------------------------
  918. // WriteTo
  919. //------------------------------------------------------------------------------
  920.  
  921. SOM_Scope void SOMLINK ODBaseTransform__WriteTo(ODBaseTransform *somSelf, Environment *ev,
  922.          ODStorageUnit *su )
  923. {
  924.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  925.     ODBaseTransformMethodDebug("ODBaseTransform","WriteTo");
  926.     
  927.     SOM_TRY
  928.     BAIL_IF_NULL(su,VOID);
  929.     
  930.     if( _fPreTransform || _fPostTransform) {
  931.         WARN("Tried to externalize composite transform %p",somSelf);
  932.     }
  933.     
  934.     ODSUForceFocus(ev,su,kODNULL,kODTransform);
  935.     ODULong size = su->GetSize(ev);
  936.     if( size!=0 )
  937.         su->DeleteValue(ev,size);        // Nuke previous contents
  938.     ODSetMatrixProp(ev, su, kODNULL,kODNULL, &_fMatrix);
  939.  
  940.     SOM_CATCH_ALL
  941.     SOM_ENDTRY
  942. }
  943.  
  944. //------------------------------------------------------------------------------
  945. // ReadFrom
  946. //------------------------------------------------------------------------------
  947.  
  948. SOM_Scope void SOMLINK ODBaseTransform__ReadFrom(ODBaseTransform *somSelf, Environment *ev,
  949.          ODStorageUnit *su )
  950. {
  951.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  952.     ODBaseTransformMethodDebug("ODBaseTransform","ReadFrom");
  953.  
  954.     SOM_TRY
  955.     
  956.     ODReleaseObject(ev,_fPreTransform);
  957.     ODReleaseObject(ev,_fPostTransform);
  958.     
  959.     BAIL_IF_NULL(su,VOID);
  960.     ODMatrix m;
  961.     ODGetMatrixProp(ev, su, kODNULL, kODTransform, &m);
  962.     somSelf->SetMatrix(ev, &m);
  963.  
  964.     SOM_CATCH_ALL
  965.     SOM_ENDTRY
  966. }
  967.